<?php

namespace pmvc\mvc;

use pmvc\mvc\controller\FormErrors;
use pmvc\data\bind\ObjectBinder;

use stdClass;

class WebFormBinder
	extends ObjectBinder {

	/**
	 * Creates a new form object, binds it to the given request
	 * parameter names and returns it. The {@link FormErrors}
	 * is populated with any binding or validation errors.
	 * 
	 * @param Request $request
	 * @param FormErrors $formErrors
	 * @param array $parameterNames
	 */
	public function bindNewForm(Request $request, FormErrors $formErrors, Array $parameterNames=Array()) {
		$ret = new stdClass();
		$this->bindForm($ret, $request, $formErrors, $parameterNames);
		return $ret;
	}

	/**
	 * Binds an existing form to the given request parameter names
	 * and returns the {@link BindResult}. The {@link FormErrors}
	 * is populated with any binding or validation errors.
	 * 
	 * @param object $object
	 * @param Request $request
	 * @param FormErrors $formErrors
	 * @param array $parameterNames
	 */
	public function bindForm(&$object, Request $request, FormErrors $formErrors, Array $parameterNames=Array()) {

		// generate field list
		$fields = Array();
		$requestParams = $request->getParameters();
		
		if (count($parameterNames) > 0) {
			// use only the specified parameters
			foreach ($parameterNames as $parameterName) {
				$fields[$parameterName] = isset($requestParams[$parameterName]) ? $requestParams[$parameterName] : null;
			}
		} else {
			// use all request parameters
			foreach ($requestParams as $parameterName => $parameterValue) {
				$fields[$parameterName] = $parameterValue;
			}
		}

		// bind
		return $this->bindValues($object, $request, $formErrors, $fields);
	}

	/**
	 * Binds the given values to the given form object and returns
	 * the {@link BindResult}.  The {@link FormErrors} is populated
	 * with any binding or validation errors.
	 * 
	 * @param object $object
	 * @param Request $request
	 * @param FormErrors $formErrors
	 * @param array $values
	 */
	public function bindValues(&$object, Request $request, FormErrors $formErrors, Array $values) {
		
		// bind
		$bindResult = parent::bind($object, $values);
		
		// add field errors
		foreach ($bindResult->getAllFieldErrors() as $fieldName => $messages) {
			foreach ($messages as $message) {
				$formErrors->addFieldError($fieldName, $message);
			}
		}
		
		// add global errors
		foreach ($bindResult->getAllObjectErrors() as $message) {
			$formErrors->addGlobalError($message);
		}

		return $bindResult;
	}

}

?>